#include "raytracing.h"
#include "sdl_auxiliary.h"
#include "sdl_screen.h"
#include "settings.h"


RayTracing::RayTracing() throw (sdl::Exception)
: _camera(CAMERA_POSITION, CAMERA_FOCAL_LEN)
, _light(LIGHT_POSITION, LIGHT_INTENSITY)
{
	_scene.generateDefault();
	sdl::Screen* s = sdl::Screen::getInstance();
	s->setCaption("Ray tracing");
	// Register callbacks
	s->addListener(this);
	sdl::Event::getInstance()->addListener(this);
	// Update on start
	s->update();
	// Enter main loop
	sdl::Event::getInstance()->wait();
	// Get a screenshot
	s->saveBmp("screenshot.bmp");
}


void RayTracing::on(sdl::SurfaceListener::Update, sdl::Surface* s) throw()
{
	Intersection is;
	static glm::vec3 black(0);

	for (int y = 0; y < s->getHeight(); y++) {
		for (int x = 0; x < s->getWidth(); x++) {

			if (_scene.closestIntersect(
				Ray(_camera.getWorldPos(), _camera.getDirection(x, y)), &is))
			{
				s->putPixel(x, y, is.triangle->getColor() *
					(_light.calcColor(is, &_scene) + INDRECT_LIGHT));
			}
			else s->putPixel(x, y, black);
		}
	}
}


void RayTracing::on(sdl::EventListener::NewEvent, const SDL_Event* e) throw()
{
	if (e->type == SDL_QUIT ||
		(e->type == SDL_KEYDOWN && e->key.keysym.sym == SDLK_ESCAPE))
	{
		sdl::Event::getInstance()->stopWaiting();
	}
}


int main()
{
	try {
		// Init SDL library
		sdl::initialize();
		// Create window
		sdl::Screen::getInstance()->setVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT);
		RayTracing();
	}
	catch (sdl::Exception& e) {
		// Get rid off warning (format not a string literal
		// and no format arguments)
		fprintf(stderr, "%s", e.what());
		return 1;
	}
	return 0;
}

